package com.glodon.gys.rest.client.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.glodon.cloudt.rest.client.RestServiceClient;
import com.glodon.cloudt.rest.client.data.HmacRestAuthInfo;
import com.glodon.cloudt.rest.client.data.RestResponseInfo;
import com.glodon.cloudt.rest.client.exception.AuthenticateException;
import com.glodon.cloudt.rest.client.exception.InvalidUriException;
import com.glodon.cloudt.rest.client.exception.NoAuthenticateException;
import com.glodon.cloudt.rest.client.impl.HmacRestServiceClientNew;
import com.glodon.cloudt.rest.client.utils.StringUtils;
import com.glodon.gys.rest.client.constant.Constants;
import com.glodon.gys.rest.client.data.PreUploadInfo;
import com.glodon.gys.rest.client.data.PutSignatureInfo;
import com.glodon.gys.rest.client.data.Result;

import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

public class GysRestClientNew {
    private static final String PUT_SIGNATURES_URL = "/api/inspection/v1.0/fs/put-url-signatures";
    private static RestServiceClient serviceClient;

    // public static void main(String[] args) throws AuthenticateException, NoAuthenticateException, InvalidUriException {
    //     GysRestClient instance = GysRestClient.getInstance("D:\\Workspace\\SDHS\\Codes\\ZHGD\\文双项目\\二部分_地磅\\auth.lic");
    //     Result result = instance.get("https://xmgl.glodon.com/gys/inspection-api-service/integrate-v2/getSLlist?projectId=&beginTimestamp=20251113014902478&hasPicture=true");
    //     System.out.println(JSON.toJSONString(result));
    // }

    public static GysRestClientNew getInstance(InputStream licStream) throws AuthenticateException {
        HmacRestAuthInfo restAuthInfo = new HmacRestAuthInfo();
        restAuthInfo.setLicStream(licStream);
        serviceClient = HmacRestServiceClientNew.getInstance();
        serviceClient.authenticate(restAuthInfo);
        return new GysRestClientNew();
    }

    public static GysRestClientNew getInstance(String licPath) throws AuthenticateException {
        HmacRestAuthInfo restAuthInfo = new HmacRestAuthInfo();
        restAuthInfo.setLicPath(licPath);
        serviceClient = HmacRestServiceClientNew.getInstance();
        serviceClient.authenticate(restAuthInfo);
        return new GysRestClientNew();
    }

    public Result uploadFile(String moduleName, Map<String, byte[]> filesMap) throws InvalidUriException, NoAuthenticateException {
        checkRequestParam(moduleName, filesMap);
        Set<String> keys = filesMap.keySet();
        PreUploadInfo preUploadInfo = makePreUploadInfo(moduleName, keys);
        RestResponseInfo uploadUrlResult = serviceClient.post(getFullUrl(PUT_SIGNATURES_URL), JSONObject.toJSONString(preUploadInfo));
        if (!uploadUrlResult.isSuccess()) {
            return responseToResult(uploadUrlResult);
        }
        List<PutSignatureInfo> putSignatureInfoList = successResultToPutSignatureInfoList(uploadUrlResult);
        if (putSignatureInfoList == null || putSignatureInfoList.isEmpty()) {
            return responseToResult(uploadUrlResult);
        }
        for (PutSignatureInfo putSignatureInfo : putSignatureInfoList) {
            String key = putSignatureInfo.getKey();
            byte[] bytes = filesMap.get(key);
            Result restResponseInfo = upload(putSignatureInfo.getValue(), bytes);
            if (!restResponseInfo.isSuccess()) {
                return restResponseInfo;
            }
        }
        return makeRestResponseInfo(putSignatureInfoList);
    }

    private Result makeRestResponseInfo(List<PutSignatureInfo> signatureInfoVos) {
        return Result.success(signatureInfoVos);
    }

    @Deprecated
    private Result upload(String restUrl, byte[] file) throws InvalidUriException, NoAuthenticateException {
        RestResponseInfo restResponseInfo = serviceClient.put(restUrl, Arrays.toString(file));
        return responseToResult(restResponseInfo);
    }

    private String getFullUrl(String restUrl) {
        return serviceClient.getRestRootAddress() + restUrl;
    }

    public Result post(String restUrl, String data, String contentType) throws InvalidUriException, NoAuthenticateException {
        RestResponseInfo restResponseInfo = serviceClient.post(getFullUrl(restUrl), data, contentType);
        return responseToResult(restResponseInfo);
    }

    public Result post(String restUrl, String data) throws InvalidUriException, NoAuthenticateException {
        RestResponseInfo restResponseInfo = serviceClient.post(getFullUrl(restUrl), data);
        return responseToResult(restResponseInfo);
    }

    public Result put(String restUrl, String data, String contentType) throws InvalidUriException, NoAuthenticateException {
        RestResponseInfo restResponseInfo = serviceClient.put(getFullUrl(restUrl), data, contentType);
        return responseToResult(restResponseInfo);
    }

    public Result put(String restUrl, String data) throws InvalidUriException, NoAuthenticateException {
        RestResponseInfo restResponseInfo = serviceClient.put(getFullUrl(restUrl), data);
        return responseToResult(restResponseInfo);
    }

    public Result get(String restUrl) throws InvalidUriException, NoAuthenticateException {
        RestResponseInfo restResponseInfo = serviceClient.get(getFullUrl(restUrl));
        return responseToResult(restResponseInfo);
    }

    private void checkRequestParam(String moduleName, Map<String, byte[]> files) {
        if (StringUtils.isEmpty(moduleName)) {
            throw new IllegalArgumentException("moduleName cannot be empty ");
        }
        if (files == null || files.isEmpty()) {
            throw new IllegalArgumentException("files cannot be empty");
        }
    }

    private PreUploadInfo makePreUploadInfo(String moduleName, Set<String> keys) {
        PreUploadInfo preUploadInfo = new PreUploadInfo();
        preUploadInfo.setModuleName(moduleName);
        preUploadInfo.setProductType(Constants.INSPECTION);
        preUploadInfo.setKeys(keys);
        preUploadInfo.setPublic(Boolean.TRUE);
        return preUploadInfo;
    }

    private List<PutSignatureInfo> successResultToPutSignatureInfoList(RestResponseInfo uploadUrlResult) {
        String stringContent = null;
        stringContent = uploadUrlResult.getStringContent();
        JSONObject jsonObject = JSON.parseObject(stringContent);
        if (jsonObject == null || !jsonObject.getBoolean(Constants.SUCCESS)) {
            return Collections.emptyList();
        }
        String dataString = keyGetJsonString(stringContent, Constants.DATA);
        String signaturesJS = keyGetJsonString(dataString, Constants.SIGNATURES);
        return JSONObject.parseArray(signaturesJS, PutSignatureInfo.class);
    }

    private static String keyGetJsonString(String string, String key) {
        JSONObject jsonObject = JSONObject.parseObject(string);
        Object data = jsonObject.get(key);
        return JSONObject.toJSONString(data);
    }

    private Result responseToResult(RestResponseInfo restResponseInfo) {
        if (!restResponseInfo.isSuccess()) {
            return Result.error(restResponseInfo.getErrorMessage());
        }
        String stringContent = null;
        stringContent = restResponseInfo.getStringContent();
        if (StringUtils.isEmpty(stringContent) && restResponseInfo.isSuccess()) {
            return Result.success();
        }
        JSONObject resultJsonObject = JSON.parseObject(stringContent);
        Boolean success = resultJsonObject.getBoolean(Constants.SUCCESS);
        Integer code = resultJsonObject.getInteger(Constants.CODE);
        Object data = resultJsonObject.get(Constants.DATA);
        Object errorVo = resultJsonObject.get(Constants.ERROR_VO);
        String errorMsg = resultJsonObject.getString(Constants.ERROR_MSG);
        if (StringUtils.isEmpty(errorMsg)) {
            errorMsg = resultJsonObject.getString(Constants.ERR_MSG);
        }
        Object resultData = data != null ? data : errorVo;
        if (!Objects.isNull(success)) {
            if (success) {
                return Result.success(resultData);
            }
            return Result.error(resultData, errorMsg);
        }
        int resultCode = 0;
        if (!Objects.isNull(code)) {
            resultCode = code;
        }
        if (resultCode == 200) {
            return Result.success(resultData);
        }
        return Result.error(resultData, errorMsg);
    }
}
